package util

import (
	"fmt"
	"math"
	"strconv"

	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
)

// PageInfo 分页参数接口
type PageInfo interface {
	GetPage() int
	GetPageSize() int
	GetOffset() int
}

// NextPageInfo 分页结果接口
type NextPageInfo interface {
	GetCurrentPage() int
	GetLastPage() int
	GetTotal() int64
	GetPerPage() int
	GetFrom() int
	GetTo() int
	HasNext() bool
	HasPrev() bool
}

// PageRequest 分页请求结构
type PageRequest struct {
	Page     int `form:"page" json:"page"`
	PageSize int `form:"page_size" json:"page_size"`
}

// GetPage 获取页码
func (p *PageRequest) GetPage() int {
	if p.Page <= 0 {
		return 1
	}
	return p.Page
}

// GetPageSize 获取每页大小
func (p *PageRequest) GetPageSize() int {
	if p.PageSize <= 0 {
		return 10
	}
	if p.PageSize > 100 {
		return 100
	}
	return p.PageSize
}

// GetOffset 获取偏移量
func (p *PageRequest) GetOffset() int {
	return (p.GetPage() - 1) * p.GetPageSize()
}

// PageResponse 分页响应结构
type PageResponse struct {
	CurrentPage int   `json:"current_page"`
	LastPage    int   `json:"last_page"`
	Total       int64 `json:"total"`
	PerPage     int   `json:"per_page"`
	From        int   `json:"from"`
	To          int   `json:"to"`
}

// GetCurrentPage 获取当前页
func (p *PageResponse) GetCurrentPage() int {
	return p.CurrentPage
}

// GetLastPage 获取最后一页
func (p *PageResponse) GetLastPage() int {
	return p.LastPage
}

// GetTotal 获取总数
func (p *PageResponse) GetTotal() int64 {
	return p.Total
}

// GetPerPage 获取每页大小
func (p *PageResponse) GetPerPage() int {
	return p.PerPage
}

// GetFrom 获取起始记录号
func (p *PageResponse) GetFrom() int {
	return p.From
}

// GetTo 获取结束记录号
func (p *PageResponse) GetTo() int {
	return p.To
}

// HasNext 是否有下一页
func (p *PageResponse) HasNext() bool {
	return p.CurrentPage < p.LastPage
}

// HasPrev 是否有上一页
func (p *PageResponse) HasPrev() bool {
	return p.CurrentPage > 1
}

// ToMap 将分页信息转换为map
func (p *PageResponse) ToMap() map[string]interface{} {
	return map[string]interface{}{
		"current_page": p.CurrentPage,
		"last_page":    p.LastPage,
		"per_page":     p.PerPage,
		"total":        p.Total,
		"from":         p.From,
		"to":           p.To,
		"has_next":     p.HasNext(),
		"has_prev":     p.HasPrev(),
	}
}

// MakePagedResponse 创建分页响应
func MakePagedResponse(data interface{}, pageInfo NextPageInfo) map[string]interface{} {
	if pageInfo == nil {
		return map[string]interface{}{
			"data": data,
		}
	}
	return map[string]interface{}{
		"data":     data,
		"pageinfo": pageInfo.(*PageResponse).ToMap(),
	}
}

// ParsePageInfo 从Gin context解析分页参数
func ParsePageInfo(c *gin.Context) PageInfo {
	page, _ := strconv.Atoi(c.DefaultQuery("page", "1"))
	pageSize, _ := strconv.Atoi(c.DefaultQuery("page_size", "10"))

	return &PageRequest{
		Page:     page,
		PageSize: pageSize,
	}
}

// Paginate GORM分页查询
func Paginate(db *gorm.DB, pageInfo PageInfo, dest interface{}) (NextPageInfo, error) {
	var total int64

	// 计算总数
	if err := db.Count(&total).Error; err != nil {
		return nil, fmt.Errorf("获取总数失败: %w", err)
	}

	// 计算分页参数
	page := pageInfo.GetPage()
	pageSize := pageInfo.GetPageSize()
	offset := pageInfo.GetOffset()

	// 执行分页查询
	if err := db.Limit(pageSize).Offset(offset).Find(dest).Error; err != nil {
		return nil, fmt.Errorf("分页查询失败: %w", err)
	}

	// 计算分页信息
	lastPage := int(math.Ceil(float64(total) / float64(pageSize)))
	from := offset + 1
	to := offset + pageSize
	if int64(to) > total {
		to = int(total)
	}
	if total == 0 {
		from = 0
	}

	return &PageResponse{
		CurrentPage: page,
		LastPage:    lastPage,
		Total:       total,
		PerPage:     pageSize,
		From:        from,
		To:          to,
	}, nil
}

// FillOption 填充选项类型
type FillOption map[string]bool
